package com.haoxuer.discover.workflow.controller.admin;

import com.haoxuer.discover.user.shiro.utils.UserUtil;
import com.haoxuer.discover.workflow.data.service.FlowService;
import com.haoxuer.discover.data.page.Page;
import com.haoxuer.discover.data.page.Pageable;
import com.haoxuer.discover.workflow.data.so.FlowSo;
import com.haoxuer.discover.workflow.data.vo.MyTaskHistoryVo;
import com.haoxuer.discover.workflow.data.vo.TaskVo;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.GraphicInfo;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

@Controller
public class WorkFlowController {
  
  protected Logger logger = LoggerFactory.getLogger(getClass());
  @Autowired
  protected RepositoryService repositoryService;
  
  @Autowired
  protected RuntimeService runtimeService;
  @Autowired
  protected TaskService taskService;
  @Autowired
  protected HistoryService historyService;
  @Autowired
  FlowService flowService;
  
  @RequestMapping("/admin/flow/approve")
  public String approve(String taskid, Integer approval, String note, HttpServletRequest request, ModelMap model) {
    
    String view = "redirect:/admin/flow/task_list.htm";
    try {
      Map<String, Object> variables = new HashMap<String, Object>();
      variables.put("approval", approval);
      taskService.setVariableLocal(taskid, "note", note);
      taskService.setVariableLocal(taskid, "user", UserUtil.getCurrentUser().getName());
      
      if (approval == 1) {
        taskService.setVariableLocal(taskid, "state", "同意");
      } else {
        taskService.setVariableLocal(taskid, "state", "不同意");
      }
      taskService.complete(taskid, variables);
      
    } catch (Exception e) {
      e.printStackTrace();
      view = "/admin/task/edit";
    }
    return view;
  }
  
  /**
   * 部署
   *
   * @param file
   * @param request
   * @return
   * @throws IOException
   */
  @RequestMapping(value = "/admin/flow/deploy")
  public String deploymentProcessDefinition_zip(@RequestParam("file") MultipartFile file, HttpServletRequest request)
      throws IOException {
    // File upload =
    // (File)file;org.springframework.web.multipart.commons.CommonsMultipartFile
    // cannot be cast to java.io.File
    InputStream upload = file.getInputStream();
    ZipInputStream zipInputStream = new ZipInputStream(upload);
    repositoryService.createDeployment().addZipInputStream(zipInputStream).deploy();
    return "redirect:/admin/flow/view_list.htm";
  }
  
  @RequestMapping(value = "/admin/flow/image")
  public String image(Model model, String taskid, Pageable pageable, HttpServletRequest request) {
    Task task = taskService.createTaskQuery().taskId(taskid).singleResult();
    model.addAttribute("task", task);
    if (task != null) {
      try {
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
            .processInstanceId(task.getProcessInstanceId()).singleResult();
        
        ProcessDefinition definition = repositoryService.getProcessDefinition(task.getProcessDefinitionId());
        ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) definition;
        
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionEntity.getId());
        
        GraphicInfo activityImpl = bpmnModel.getGraphicInfo(task.getTaskDefinitionKey());
        model.addAttribute("x", activityImpl.getX());
        model.addAttribute("y", activityImpl.getY());
        model.addAttribute("width", activityImpl.getWidth());
        model.addAttribute("height", activityImpl.getHeight());
      } catch (Exception e) {
      
      }
      
    }
    return "/admin/flow/image";
  }
  
  /**
   * 读取资源，通过部署ID（部署时使用） 查看图片资源或者xml资源
   *
   * @param processDefinitionId 流程定义
   * @param resourceType        资源类型(xml|image)
   * @throws Exception
   */
  @RequestMapping(value = "/admin/flow/read")
  public void loadByDeployment(@RequestParam("processDefinitionId") String processDefinitionId,
                               @RequestParam("resourceType") String resourceType, HttpServletResponse response) throws Exception {
    ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
        .processDefinitionId(processDefinitionId).singleResult();
    String resourceName = "";
    if (resourceType.equals("image")) {
      resourceName = processDefinition.getDiagramResourceName();
    } else if (resourceType.equals("xml")) {
      resourceName = processDefinition.getResourceName();
    }
    InputStream resourceAsStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(),
        resourceName);
    byte[] b = new byte[1024];
    int len = -1;
    while ((len = resourceAsStream.read(b, 0, 1024)) != -1) {
      response.getOutputStream().write(b, 0, len);
    }
  }
  
  @RequestMapping(value = "/admin/flow/task_list")
  public String myTaskList(Model model, FlowSo so, Pageable pageable, HttpServletRequest request) {
    Page<TaskVo> page = flowService.page(UserUtil.getCurrentUser().getId() + "", pageable, so);
    List<TaskVo> taskVoList = page.getContent();
    model.addAttribute("page", page);
    model.addAttribute("so", so);
    return "/admin/flow/my_task_list";
  }
  
  @RequestMapping(value = "/admin/flow/my_his_task_list")
  public String myHisTaskList(Model model, FlowSo so, Pageable pageable, HttpServletRequest request) {
    Page<TaskVo> page = flowService.page(UserUtil.getCurrentUser().getId() + "", pageable, so);
    List<TaskVo> taskVoList = page.getContent();
    model.addAttribute("page", page);
    model.addAttribute("so", so);
    return "/admin/flow/my_task_list";
  }
  
  /**
   * 系统中部署了多少工作流
   *
   * @param model
   * @param request
   * @return
   */
  @RequestMapping(value = "/admin/flow/view_list")
  public String processDefinitionList(Model model, String name, HttpServletRequest request) {
        /*
     * 只读取表单：leave-formkey
		 */
    if (name == null) {
      name = "";
    }
    
    
    ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery().processDefinitionNameLike("%" + name + "%").latestVersion()
        .orderByProcessDefinitionName().desc();
    List<ProcessDefinition> list = query.list();
    model.addAttribute("list", list);
    model.addAttribute("name", name);
    
    return "/admin/flow/list";
  }
  
  @RequestMapping(value = "/admin/flow/records")
  public String records(Model model, String businessKey, HttpServletRequest request) {
    model.addAttribute("records", flowService.records(businessKey));
    
    return "/admin/flow/records";
  }
  
  @RequestMapping(value = "/admin/flow/task")
  public String task(Model model, String taskid, HttpServletRequest request, Integer type) {
    Task task = taskService.createTaskQuery().taskId(taskid).singleResult();
    model.addAttribute("task", task);
    model.addAttribute("type", type);
    
    model.addAttribute("model", taskService.getVariables(taskid));
    
    ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
        .processInstanceId(task.getProcessInstanceId()).singleResult();
    model.addAttribute("records", flowService.records(processInstance.getBusinessKey()));
    
    return "/admin/flow/taskview";
  }
  
  @RequestMapping(value = "/admin/flow/task_list_all")
  public String taskList(Model model, FlowSo so, Pageable pageable, HttpServletRequest request) {
    Page<TaskVo> page = flowService.page(pageable, so);
    model.addAttribute("list", page.getContent());
    model.addAttribute("page", page);
    model.addAttribute("so", so);
    return "/admin/flow/task_list";
  }
  
  @RequestMapping(value = "/admin/flow/view_add")
  public String view_add(Model model) {
    
    return "admin/flow/add";
  }
  
  @RequestMapping(value = "/admin/flow/view_view")
  public String view_view(Model model, @RequestParam("processDefinitionId") String processDefinitionId,
                          @RequestParam("resourceType") String resourceType) {
    model.addAttribute("processDefinitionId", processDefinitionId);
    model.addAttribute("resourceType", resourceType);
    return "admin/flow/view";
  }
  
  @RequestMapping(value = "/admin/flow/my_his")
  public String myHis(Model model, FlowSo so, Pageable pageable, HttpServletRequest request) {
    Page<MyTaskHistoryVo> page = flowService.pageHis(pageable, so);
    model.addAttribute("list", page.getContent());
    model.addAttribute("page", page);
    model.addAttribute("so", so);
    return "/admin/flow/my_history";
  }
  
}
